package com.AdvancedDemos.LearnVariousAPI.时间日期类.JDK8新时间日期类;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

public class LearnLocalDateTime {

    /**
     * JDK8之前的传统时间类:
     * 1.设计不合理,使用不方便,很多都被淘汰了
     * 2.都是可变对象,修改后会丢失最开始的时间信息
     * 3.现成不安全
     * 4.只能精确到毫秒
     * <p>
     * JDK8新增的时间类:
     * 1.设计更合理,功能更丰富,使用更方便
     * 2.都是不可变对象,修改后会返回新的时间对象,不会丢失最开始的时间
     * 3.线程安全
     * 4.能精确到毫秒,纳秒
     * <p>
     * 1秒 = 1000毫秒
     * 1毫秒 = 1000微秒
     * 1微秒 = 1000纳秒
     * 1秒 = 1E9纳秒
     */
    public static void main(String[] args) {
        //JDK8开始提供了3个更方便的操作日期时间的类
        // LocalDate : 代表本地日期(年,月,日,星期)
        // LocalTime : 代表本地时间(时,分,秒,纳秒)
        // LocalDateTime : 代表本地日期,时间(年,月,日,星期,时,分,秒,纳秒)
        //用于替代Calendar

        /*
        1.三者都有静态函数now
        public static XXX now() --- 获取系统当前时间对应的对象
        LocalDate ld = LocalDate.now();
        LocalTime lt = LocalTime.now();
        LocalDateTime ldt = LocalDateTime.now();
         */

        System.out.println("----------------");
        LocalDate ld = LocalDate.now();
        System.out.println("LocalDate : " + ld);//LocalDate : 2023-03-06
        LocalTime lt = LocalTime.now();
        System.out.println("LocalTime : " + lt);//LocalTime : 14:36:06.082771500
        LocalDateTime ldt = LocalDateTime.now();
        System.out.println("LocalDateTime : " + ldt);//LocalDateTime : 2023-03-06T14:38:30.721490500


        /*
        2.获取日期对象中的信息 getXXX系列函数
         */
        System.out.println("----------------");
        System.out.println(ld.getYear() + "年");
        System.out.println(ld.getMonth());//月份英文
        System.out.println(ld.getMonth().getValue() + "月");//月份数值
        System.out.println(ld.getMonthValue() + "月");//月份数值

        System.out.println(ld.getDayOfMonth() + "日");//日期
        System.out.println(ld.getDayOfWeek());//星期英文
        System.out.println("星期" + ld.getDayOfWeek().getValue());//星期数值
        System.out.println(lt.getHour() + "时");//秒
        System.out.println(lt.getMinute() + "分");//秒
        System.out.println(lt.getSecond() + "秒");//秒
        System.out.println(lt.getNano() + "纳秒");//纳秒


        /*
        3.直接修改某个信息 withXXX系列函数
         */
        System.out.println("----------------");
        LocalDate future = ld.withYear(2077);
        future = future.withMonth(7);
        future = future.withDayOfMonth(7);
        System.out.println("withXXX修改后新的LocalDate对象为 : " + future);
        System.out.println("原对象与新对象是同一个对象吗 ? " + (future == ld ? "是" : "不是"));//withXXX系列会返回新对象,原来的对象不变
        System.out.println("原对象为 : " + ld);



        /*
        4.把某个信息 加/减 多少 plusXXX & minusXXX 系列函数
         */
        System.out.println("----------------");
        LocalDate future1 = ld.plusDays(1);//加1天
        future1 = future1.plusWeeks(1);//加一周,7天
        future1 = future1.minusMonths(1);//减1个月
        future1 = future1.minusYears(3);//减3年
        System.out.println("原LocalDate对象加减后的新LocalDate对象为 : " + future1);



        /*
        5.用静态函数of 获取指定日期时间的LocalDate LocalDateTime LocalTime对象
         */
        System.out.println("----------------");
        ld = LocalDate.of(2099, 12, 12);
//        ldt = LocalDateTime.of(2500, 2, 28, 12, 12, 12);
        System.out.println(ld);




        /*
        6.判断日期时间先后顺序,是否相等 isXXX系列 (isBefore isAfter isEqual) 函数
         */
        System.out.println("----------------");
        System.out.println(ld.isBefore(future1));
        System.out.println(ld.isAfter(future1));
        System.out.println(ld.isEqual(future1));
        System.out.println(ld.isEqual(ld));
        System.out.println(ld.equals(future1));
        System.out.println(ld.equals(ld));
        //isEqual是LocalDate/LocalTime/LocalDateTime自己的方法,直接比较对象属性值
        //equals是Object类中重写的函数,内部将时间LocalTime和日期LocalDate分成两种对象再各自执行各自重写的equals
        //isEqual equals两者效果一致,但是isEqual更内部简单


        /*
        7.LocalDate LocalDateTime LocalTime 三个类操作函数名几乎完全相同,只是类不同相互,可以转换
        */
        //LocalDateTime -> LocalDate
        System.out.println("----------------");
        LocalDate localDate = ldt.toLocalDate();
        System.out.println(localDate);

        //LocalDateTime -> LocalTime
        System.out.println("- - - - - - - -");
        LocalTime localTime = ldt.toLocalTime();
        System.out.println(localTime);

        //LocalDate + LocalTime -> LocalDateTime
        System.out.println("- - - - - - - -");
        LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
        System.out.println(localDateTime);


        System.out.println("----------------");
        /**
         * 快递发货案例:
         *
         * 用户如果是当天下午3:00之前下单,第二天下午3:00之前发货
         * 如果是当天下午3:00之后下单,第三天下午3:00之前发货
         * 如果当天是周日,则额外增加一天(由于快递公司休息)
         *
         * 根据用户下单时间,给出发货时间:
         */

        LocalDateTime 下单时间 = LocalDateTime.of(2023, 3, 4, 14, 40, 0);
        System.out.println("下单时间:" + 下单时间 + " " + 下单时间.getDayOfWeek());
        LocalDateTime 发货时间;
        LocalDate 发货日期 = 下单时间.toLocalDate();
        LocalTime 当天15点 = LocalTime.of(15, 0, 0);
        if (下单时间.toLocalTime().isBefore(当天15点)) {
            发货日期 = 发货日期.plusDays(1);
            发货时间 = LocalDateTime.of(发货日期, 当天15点);
        } else {
            发货日期 = 发货日期.plusDays(2);
            发货时间 = LocalDateTime.of(发货日期, 当天15点);
        }
        if (发货时间.getDayOfWeek() == DayOfWeek.SUNDAY/*等价于 发货时间.getDayOfWeek().getValue() == 7*/) {
            发货时间 = 发货时间.plusDays(1);
        }
        System.out.println("发货时间:" + 发货时间 + " " + 发货时间.getDayOfWeek());

    }
}
